package com.quiz.bis.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.quiz.bis.domain.bo.PaperBO;
import com.quiz.bis.domain.bo.PaperQuestionBO;
import com.quiz.bis.domain.model.*;
import com.quiz.bis.domain.vo.*;
import com.quiz.bis.mapper.*;
import com.quiz.bis.service.IPaperService;
import com.quiz.bis.template.pdf.PaperHTML;
import com.quiz.bis.util.pdf.ExportPaperWordUtil;
import com.quiz.bis.util.pdf.PdfUtil;
import com.quiz.common.core.domain.R;
import com.quiz.common.core.domain.model.LoginUser;
import com.quiz.common.exception.ServiceException;
import com.quiz.common.mybatis.core.page.PageQuery;
import com.quiz.common.mybatis.core.page.TableDataInfo;
import com.quiz.common.mybatis.core.query.PlusWrappers;
import com.quiz.common.utils.SecurityUtils;
import com.quiz.common.utils.StringUtils;
import com.quiz.common.utils.bean.BeanUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 试卷服务层实现
 *
 * @author ahuan
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PaperServiceImpl implements IPaperService {

    private final PaperMapper paperMapper;
    private final PaperQuestionMapper paperQuestionMapper;
    private final QuestionMapper questionMapper;
    private final QuestionStatisticsMapper questionStatisticsMapper;
    private final QuestionTagRelationMapper questionTagRelationMapper;
    private final TagMapper tagMapper;
    private final ExportPaperWordUtil exportPaperWordUtil;
    private final PaperHTML paperHTML;

    @Override
    @Transactional
    public R<Long> createPaper(PaperBO paperBO) {
        // 验证试卷标题和编码
        if (StringUtils.isBlank(paperBO.getTitle())) {
            return R.fail("试卷标题不能为空");
        }

        if (StringUtils.isBlank(paperBO.getCode())) {
            return R.fail("试卷编码不能为空");
        }

        // 检查编码是否已存在
        if (paperMapper.exists(Wrappers.<Paper>lambdaQuery()
                .eq(Paper::getCode, paperBO.getCode())
                .eq(Paper::getDelFlag, 0))) {
            return R.fail("试卷编码已存在");
        }

        // 计算总分
        BigDecimal totalScore = paperBO.getQuestions().stream()
                .map(PaperQuestionBO::getScore)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 创建试卷
        Paper paper = BeanUtil.copyProperties(paperBO, Paper.class);
        paper.setTotalScore(totalScore);
        paper.setStatus(0); // 草稿状态
        paper.setVersion(1);

        paperMapper.insert(paper);

        // 保存试卷题目关联
        savePaperQuestions(paper.getId(), paperBO.getQuestions());

        return R.ok(paper.getId());
    }

    private void savePaperQuestions(Long paperId, List<PaperQuestionBO> questions) {
        if (CollUtil.isEmpty(questions)) {
            return;
        }

        List<PaperQuestion> paperQuestions = questions.stream()
                .map(bo -> {
                    PaperQuestion pq = new PaperQuestion();
                    BeanUtils.copyProperties(bo, pq);
                    pq.setPaperId(paperId);
                    pq.setDelFlag(0);
                    return pq;
                })
                .collect(Collectors.toList());

        paperQuestionMapper.insertBatch(paperQuestions);

        // 更新题目统计信息
        updateQuestionStatistics(questions);
    }

    private void updateQuestionStatistics(List<PaperQuestionBO> questions) {
        List<Long> questionIds = questions.stream()
                .map(PaperQuestionBO::getQuestionId)
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(questionIds)) {
            return;
        }

        // 批量更新题目统计信息
        questionStatisticsMapper.batchUpdatePaperCount(questionIds, SecurityUtils.getUserId());
    }


    @Override
    public R<PaperVO> getPaperDetail(Long paperId) {
        Paper paper = paperMapper.selectById(paperId);
        if (paper == null || paper.getDelFlag() == 1) {
            return R.fail("试卷不存在或已删除");
        }

        PaperVO paperVO = new PaperVO();
        BeanUtils.copyProperties(paper, paperVO);

        // 获取试卷题目
        List<PaperQuestionVO> questions = paperQuestionMapper.selectQuestionListByPaperId(paperId);
        paperVO.setQuestions(questions);

        return R.ok(paperVO);
    }

    @Override
    public R<Void> updatePaper(PaperBO paperBO) {
        if (paperBO.getId() == null) {
            return R.fail("试卷ID不能为空");
        }

        Paper paper = paperMapper.selectById(paperBO.getId());
        if (paper == null || paper.getDelFlag() == 1) {
            return R.fail("试卷不存在或已删除");
        }

        // 更新试卷基本信息
        BeanUtils.copyProperties(paperBO, paper);

        // 重新计算总分
        BigDecimal totalScore = paperBO.getQuestions().stream()
                .map(PaperQuestionBO::getScore)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        paper.setTotalScore(totalScore);

        paperMapper.updateById(paper);

        // 先删除原有题目关联
        paperQuestionMapper.delete(Wrappers.<PaperQuestion>lambdaQuery()
                .eq(PaperQuestion::getPaperId, paper.getId()));

        // 保存新的题目关联
        savePaperQuestions(paper.getId(), paperBO.getQuestions());

        return R.ok();
    }

    @Override
    public R<Void> deletePaper(Long paperId) {
        Paper paper = paperMapper.selectById(paperId);
        if (paper == null || paper.getDelFlag() == 1) {
            return R.fail("试卷不存在或已删除");
        }

        // 逻辑删除
        paper.setDelFlag(1);
        paperMapper.updateById(paper);

        return R.ok();
    }


    @Override
    public R<PaperPreviewVO> previewPaper(Long paperId, PreviewOptions options) {
        Paper paper = paperMapper.selectById(paperId);
        if (paper == null || paper.getDelFlag() == 1) {
            return R.fail("试卷不存在或已删除");
        }

        PaperPreviewVO previewVO = new PaperPreviewVO();
        BeanUtils.copyProperties(paper, previewVO);

        // 获取试卷题目详情列表
        List<PaperQuestionDetailVO> questions = paperQuestionMapper.selectQuestionDetailListByPaperId(paperId);

        // 补充知识点和难度信息
//        enrichQuestionDetails(questions);

        // 按题型分组
        Map<String, List<PaperQuestionDetailVO>> questionsByType = questions.stream()
                .collect(Collectors.groupingBy(PaperQuestionDetailVO::getTypeName));

        previewVO.setQuestionsByType(questionsByType);

        // 设置预览选项
        if (options != null) {
            previewVO.setPreviewOptions(options);
        } else {
            // 默认显示所有内容
            PreviewOptions defaultOptions = new PreviewOptions();
            defaultOptions.setShowAnswers(true);
            defaultOptions.setShowOptionAnswers(true);
            defaultOptions.setShowAnalysis(true);
            defaultOptions.setShowKnowledgePoints(true);
            defaultOptions.setShowDifficulty(true);
            previewVO.setPreviewOptions(defaultOptions);
        }

        return R.ok(previewVO);
    }


    private void enrichQuestionDetails(List<PaperQuestionDetailVO> questions) {
        // 批量查询知识点标签
        List<Long> questionIds = questions.stream()
                .map(PaperQuestionDetailVO::getQuestionId)
                .collect(Collectors.toList());

        if (!questionIds.isEmpty()) {
            // 查询题目关联的知识点标签
            List<QuestionTagRelation> relations = questionTagRelationMapper.selectList(
                    Wrappers.<QuestionTagRelation>lambdaQuery()
                            .in(QuestionTagRelation::getQuestionId, questionIds)
                            .eq(QuestionTagRelation::getDelFlag, 0)
            );

            // 查询标签详情
            List<Long> tagIds = relations.stream()
                    .map(QuestionTagRelation::getTagId)
                    .distinct()
                    .collect(Collectors.toList());

            Map<Long, String> tagMap = tagMapper.selectList(
                    PlusWrappers.lambdaQuery(Tag.class)
                            .inIfPresent(Tag::getId, tagIds)
                            .eq(Tag::getDelFlag, 0)

            ).stream().collect(Collectors.toMap(Tag::getId, Tag::getName));

            // 构建题目-知识点映射
            Map<Long, List<String>> questionKnowledgeMap = relations.stream()
                    .collect(Collectors.groupingBy(
                            QuestionTagRelation::getQuestionId,
                            Collectors.mapping(
                                    r -> tagMap.get(r.getTagId()),
                                    Collectors.toList()
                            )
                    ));

            // 设置题目知识点
            questions.forEach(q -> {
                q.setKnowledgePoints(questionKnowledgeMap.getOrDefault(q.getQuestionId(), Collections.emptyList()));
            });
        }
    }

    @Override
    public TableDataInfo<PaperListVO> pagePaperList(PageQuery pageQuery, PaperQuery query) {
        // 设置部门过滤
//        if (!SecurityUtils.isAdmin()) {
//            query.setDeptId(SecurityUtils.getDeptId());
//        }


        // 查询分页数据
        Page<PaperListVO> list = paperMapper.selectPaperPageList(pageQuery.build(), query);
        return TableDataInfo.build(list);
    }

    @Override
    public void updateStatusBatch(List<Long> ids, Integer status) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        paperMapper.updateStatusBatch(ids, status, loginUser.getUserId().toString());
    }

    @Override
    public void deletePaper(List<Long> ids) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        paperMapper.delete(
                Wrappers.<Paper>lambdaUpdate()
                        .set(Paper::getDelFlag, 1)
                        .set(Paper::getUpdateBy, loginUser.getUsername())
                        .set(Paper::getUpdateTime, new Date())
                        .in(Paper::getId, ids)
        );
    }

    @Override
    public void recoverPaper(List<Long> ids) {
//        LoginUser loginUser = SecurityUtils.getLoginUser();
//        paperMapper.recover(
//                Wrappers.<Paper>lambdaUpdate()
//                        .set(Paper::getDelFlag, 0)
//                        .set(Paper::getUpdateBy, loginUser.getUsername())
//                        .set(Paper::getUpdateTime, new Date())
//                        .in(Paper::getId, ids)
//        );
    }

    @Override
    public void exportPaper(Long paperId, String exportType, PreviewOptions options,
                            HttpServletResponse response, HttpServletRequest request) {
        // 获取试卷详情
        R<PaperPreviewVO> result = previewPaper(paperId, options);
        if (!R.isSuccess(result)) {
            throw new ServiceException(result.getMsg());
        }

        PaperPreviewVO paper = result.getData();

        // 根据导出类型生成文件
        if ("pdf".equalsIgnoreCase(exportType)) {
            String html = paperHTML.builder(paper, request);
            PdfUtil.exportToPdf(html, paper.getTitle() + ".pdf", response);
        } else if ("word".equalsIgnoreCase(exportType)) {
            exportPaperWordUtil.exportWord(paper, response);
        } else {
            throw new ServiceException("不支持的导出类型");
        }
    }


}